package cn.chinaunicom.admin.service.impl;

import java.util.*;

import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.easy.secret.codec.SM4Codec;

import cn.chinaunicom.admin.entity.AppServer;
import cn.chinaunicom.admin.entity.DigitalEnvelope;
import cn.chinaunicom.admin.entity.bo.RgstBO;
import cn.chinaunicom.admin.entity.form.RgstForm;
import cn.chinaunicom.admin.service.IAppServerService;
import cn.chinaunicom.admin.service.IDigitalEnvelopService;
import cn.chinaunicom.fast.common.constant.Constants;
import cn.chinaunicom.fast.common.constant.RedisKeys;
import cn.chinaunicom.fast.common.exception.AuthErrorType;
import cn.chinaunicom.fast.common.exception.BaseException;
import cn.chinaunicom.fast.common.exception.ServiceException;
import cn.chinaunicom.fast.common.utils.MyCache;
import lombok.extern.slf4j.Slf4j;

/**
 * @ProjectName: esay-secret-server
 * @Package: cn.chinaunicom.admin.service.impl
 * @ClassName: AppServerServiceImpl
 * @Description: 应用业务处理类
 * @Author: wangjc
 * @CreateDate: 2023/11/24
 * @UpdateUser: wangjc
 * @UpdateDate: 2023/11/24
 * @UpdateRemark: 更新内容
 * @Version: 1.0
 */

@Slf4j
@Service
public class AppServerServiceImpl implements IAppServerService {

    @Autowired
    private MyCache cache;

    @Autowired
    private IDigitalEnvelopService deService;

    @Override
    public AppServer add(AppServer app) {
        app.setAppId(IdWorker.getIdStr());
        app.setSecretKey(IdWorker.getTimeId());
        app.setCdate(new Date());
        app.setCuser(Constants.SYSADMIN_USER);
        app.setSts(Constants.STR_YES_ONE);

        this.saveApp(app);
        return app;
    }

    private List<AppServer> getList() {
        List<AppServer> list = (List<AppServer>) this.cache.getCache(RedisKeys.APP_SERVER_LIST);
        return (list == null) ? new ArrayList<AppServer>() : list;
    }

    private void saveApp(AppServer app) {
        cache.setCache(RedisKeys.APP_SERVER_INFO + app.getAppId(), app);
        List<AppServer> list = getList();
        boolean isExists = list.stream().anyMatch(a -> a.getAppId().equals(app.getAppId()));
        if (isExists) {
            list.parallelStream().filter(a -> a.getAppId().equals(app.getAppId())).forEach(a -> a = app);
        } else {
            list.add(app);
        }

        cache.setCache(RedisKeys.APP_SERVER_LIST, list);
    }

    @Override
    public void disabeld(AppServer app) {
        AppServer appCache = this.get(app);
        if(Objects.isNull(appCache)) {
            throw new BaseException(AuthErrorType.USER_PSWD_ERROR);
        }
        if(!appCache.getSecretKey().equals(app.getSecretKey())) {
            throw new ServiceException("secret key is error, please check your configuration");
        }

        appCache.setSts(Constants.STR_NO_ZERO);
        appCache.setUdate(new Date());
        appCache.setUuser(Constants.SYSADMIN_USER);
        this.saveApp(app);
    }

    @Override
    public String getAccessToken(AppServer app) {
        AppServer appCache = this.get(app);
        if(Objects.isNull(appCache)) {
            throw new BaseException(AuthErrorType.USER_PSWD_ERROR);
        }
        if(appCache.getSts().equals(Constants.STR_NO_ZERO)) {
            throw new BaseException(AuthErrorType.USER_PSWD_ERROR);
        }
        if(!appCache.getSecretKey().equals(app.getSecretKey())) {
            throw new BaseException(AuthErrorType.USER_PSWD_ERROR);
        }

        String accessToken = IdWorker.get32UUID();
        // app认证成功 设置认证缓存
        cache.setCache(RedisKeys.APP_LONIN_INFO + accessToken, appCache);
        return accessToken;
    }

    @Override
    public AppServer get(AppServer app) {
        return (AppServer) cache.getCache(RedisKeys.APP_SERVER_INFO + app.getAppId());
    }

    @Override
    public AppServer upd(AppServer app) {
        AppServer oldApp = this.get(app);
        BeanUtils.copyProperties(app, oldApp);
        oldApp.setUuser(Constants.SYSADMIN_USER);
        oldApp.setUdate(new Date());
        oldApp.setSts(Constants.STR_YES_ONE);

        this.saveApp(oldApp);
        return oldApp;
    }

    @Override
    public List<AppServer> getAll() {
        return getList();
    }

    @Override
    public RgstBO register(RgstForm form) {
        // 1. 新增应用
        AppServer app = new AppServer();
        BeanUtils.copyProperties(form, app);
        app = this.add(app);

        // 2. 生成sm4密钥
        String key = Optional.ofNullable(form.getPriKey()).orElse(SM4Codec.generateKey());
        String iv = Optional.ofNullable(form.getIv()).orElse(SM4Codec.getIvParameter());
        log.debug("key = {}, iv = {}", key, iv);
        String hexKey = ByteUtils.toHexString(key.getBytes());
        log.debug("hexKey = {}", hexKey);

        // 3. 生成数字信封
        DigitalEnvelope de = new DigitalEnvelope();
        de.setCompartId(app.getAppId());
        de.setCompartName(app.getAppName());
        de.setPriKey(hexKey);
        de.setDeType(form.getDeType());
        de = this.deService.add(de);

        // 4. 根据app信息进行登录
        String accessToken = this.getAccessToken(app);
        return RgstBO.builder()
                .appId(app.getAppId())
                .secretKey(app.getSecretKey())
                .deId(de.getDeId())
                .accessToken(accessToken)
                .ivParam(iv)
                .build();
    }

}
